using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using mEdit.Properties;

namespace mEdit.Controls
{
    [ToolboxBitmap(typeof(TreeView))]
    public partial class mTreeView : System.Windows.Forms.TreeView, ISaveableContent
    {
        private static string DefaultRootNodeName = "rootNode";
        private static string DefaultNodeName = "newNode";

        public event EventHandler SwapFocus;
        public event EventHandler ContentChanged;
        public event EventHandler ContentSaveRequest;

        private string _fileName = string.Empty;
        private bool _isContentChanged = false;

        private TreeNode _lastSelectedNode;
        [Browsable(false)]
        public TreeNode LastSelectedNode
        {
            get { return _lastSelectedNode; }
            set
            {
                _lastSelectedNode = value;
            }
        }

        /// <summary>
        /// Returns true if selected node is root node
        /// </summary>
        [Browsable(false)]
        public bool IsRootNode
        {
            get { return this.SelectedNode.Level == 0; }
        }

        // ctor
        public mTreeView()
        {
            InitializeComponent();

            _isContentChanged = false;
            this.BeforeSelect += new TreeViewCancelEventHandler(mTreeView_BeforeSelect);
        }

        private TreeNode CreateNode()
        {
            TreeNode node = new TreeNode();
            if (this.Nodes.Count == 0)
                node.Text = DefaultRootNodeName;
            else
                node.Text = DefaultNodeName;
            FireContentChanged();
            return node;
        }

        /// <summary>
        /// Sets the content of the previously selected node 
        /// (saves changes of node content)
        /// </summary>
        /// <param name="text"></param>
        public void SetLastSelectedNodeContent(string text)
        {
            if (this.LastSelectedNode == null)
            {
                this.LastSelectedNode = this.SelectedNode;
                this.LastSelectedNode.Tag = text;
                return;
            }
            else
            {
                this.LastSelectedNode.Tag = text;
            }
        }

        private void mTreeView_BeforeSelect(object sender, EventArgs e)
        {
            _lastSelectedNode = this.SelectedNode;
        }

        private void mTreeView_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (e.CancelEdit)
                return;
            if (!string.IsNullOrEmpty(e.Label))
            {
                this.SelectedNode.Text = e.Label;
                FireContentChanged();
            }
        }

        // ==== public methods

        public void RenameCurrentNode()
        {
            if (this.SelectedNode == null)
                return;
            this.SelectedNode.BeginEdit();
        }

        public void AddChildNode()
        {
            if (this.SelectedNode == null)
                return;
            TreeNode node = CreateNode();
            this.SelectedNode.Nodes.Add(node);
        }

        public void AddRootNode()
        {
            TreeNode node = CreateNode();
            this.Nodes.Add(node);
        }

        public void AddSiblingNode()
        {
            if ((this.SelectedNode == null) || (this.SelectedNode.Parent == null))
                return;
            TreeNode node = CreateNode();
            this.SelectedNode.Parent.Nodes.Add(node);
        }

        public void RemoveNode()
        {
            if (this.SelectedNode == null)
                return;

            TreeNode node = this.SelectedNode;
            this.SelectedNode = null;
            TreeNode parent = node.Parent ?? node.PrevNode;

            node.Remove();

            if (parent != null)
                this.LastSelectedNode = parent;

            if ((this.Nodes.Count > 0) && (parent == null))
                this.LastSelectedNode = this.Nodes[0];

            this.SelectedNode = this.LastSelectedNode;
            FireContentChanged();
        }


        private bool CheckAndSaveContent()
        {
            if (_isContentChanged)
            {
                DialogResult result = MessageBox.Show("Content not saved! Save now or lose changes?", "Warning", MessageBoxButtons.YesNo);
                if (result == DialogResult.OK)
                    this.Save();
                else
                    return false;
            }
            return true;
        }

        public bool GetFileName()
        {
            if (string.IsNullOrEmpty(_fileName))
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.AddExtension = true;
                sfd.Filter = "mEdit Files (*.med)|*.med";
                if (sfd.ShowDialog() == DialogResult.OK)
                    _fileName = sfd.FileName;
            }

            return !string.IsNullOrEmpty(_fileName);
        }

        public void NotifyContentSaved()
        {
            _isContentChanged = false;
        }
        
        // ==== end of: public methods

        private void FireContentChanged()
        {
            if (ContentChanged != null)
                ContentChanged(this, EventArgs.Empty);
        }

        private void ForceFocusSwap()
        {
            if (SwapFocus != null)
                SwapFocus(this, EventArgs.Empty);
        }

        private void mTreeView_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.S)
            {
                e.IsInputKey = true;
            }
        }

        private void mTreeView_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Control && e.KeyCode == Keys.T)
                || (e.Control && e.KeyCode == Keys.Tab))
            {
                ForceFocusSwap();
                e.SuppressKeyPress = true;
                e.Handled = true;
            } else
            if (e.Control && e.KeyCode == Keys.S)
            {
                if (ContentSaveRequest != null)
                    ContentSaveRequest(this, EventArgs.Empty);
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
        }

        //==== Drag&Drop
        private void mTreeView_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
            {
                TreeView tv = sender as TreeView;
                if (tv == null)
                    return;
                TreeNode movedNode = e.Data.GetData("System.Windows.Forms.TreeNode") as TreeNode;
                if (movedNode == null)
                    return;
                TreeNode movedClone = movedNode.Clone() as TreeNode;
                if (movedNode == null)
                    return;

                Point p = tv.PointToClient(new Point(e.X, e.Y));
                TreeNode targetNode = tv.GetNodeAt(p);
                targetNode.Nodes.Add(movedClone);
                targetNode.Expand();
                movedNode.Remove();
            }
        }

        private void mTreeView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Move);
        }

        private void mTreeView_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        // ==== end of: Drag & Drop

        public void CreateNew()
        {
            this.Nodes.Clear();
            TreeNode rootNode = this.CreateNode();
            this.Nodes.Add(rootNode);
            // TODO: remove
            //this.LastSelectedNode = rootNode;
            this._fileName = string.Empty;
            _isContentChanged = false;
        }

        public void ResetTheOnlyRootNode()
        {
            if (this.Nodes.Count != 1)
                return;
            this.Nodes[0].Text = mTreeView.DefaultRootNodeName;
        }
    }
}